/**
  ETFAna project, Anyang Normal University && IMP-CAS
  \class ETFPlaHit
  \brief for a hit in a plastic scintillator coupled at 1 or 2 ends with PMT(s)
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021-10-29
  \date 2021-11-30 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2021-10-29   <td>Asia Sun    <td>file created                  </tr>
  </table>

  \copyright Copyright (c) 2021-2024 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#ifndef ETFPlaHit_h
#define ETFPlaHit_h

#include "ETFHit.h"

class ETFRawChannel;
class ETFHPTDCCh;
class ETFAmpCh;

class ETFPlaHit : public ETFHit{
public:
  ETFPlaHit();
  ETFPlaHit(const ETFPlaHit &t); ///< copy ctor
  ETFPlaHit &operator=(const ETFPlaHit &t); ///< assignment ctor
  virtual ~ETFPlaHit();

  virtual void Initialize() override;
  /// pile up analysis
  /// \param np nof particles \param dtm min dt between trig-gen par and a adjacent par
  virtual void PileUpAna(int &np, double &dtm, double trigLB, double trigHB);
  void SetStripId(int id){ fStripId = id; }
  /// \param udvh: 0-1-2-3: uv-uh-dv-dh
  void SetTChannel(const ETFRawChannel *ch, int udvh);
  void SetQChannel(const ETFRawChannel *ch, int ud);
  void SetLength(double l){ fLength = l; }

  /// \param udvh: [0-1-2-3]: [UV, UH, DV, DH]
  const ETFHPTDCCh *GetTChannel(int udvh) const;
  const ETFAmpCh *GetQChannel(int ud) const;
  const ETFHPTDCCh *tc(int udvh) const{ return GetTChannel(udvh); }
  const ETFAmpCh *qc(int ud) const{ return GetQChannel(ud); }
  double GetTime() const{ return fTime; }
  double time() const{ return fTime; }
  double GetTimeU() const{ return fTimeL; }
  double GetTimeL() const{ return fTimeL; }
  double timeU() const{ return fTimeL; }
  double timeL() const{ return fTimeL; }
  double GetTimeD() const{ return fTimeR; }
  double GetTimeR() const{ return fTimeR; }
  double timeD() const{ return fTimeR; }
  double timeR() const{ return fTimeR; }
  double dt(){ return fTimeL - fTimeR; } ///< distance to L
  int firedU() const{ return fTimeL > 0.; } ///< fired status of up end
  int firedL() const{ return fTimeL > 0.; } ///< fired status of left end
  int firedD() const{ return fTimeR > 0.; } ///< fired status of down end
  int firedR() const{ return fTimeR > 0.; } ///< fired status of right end
  /// q info ///
  double tot() const; ///< average of the tot-s of the two ends
  double totH() const; ///< average of the tot-s of the two ends - the H (SFE) channel
  double GetQ() const{ return fQ; }
  double q() const{ return fQ; }
  double GetQU() const{ return fQL; }
  double GetQL() const{ return fQL; }
  double qu() const{ return fQL; }
  double ql() const{ return fQL; }
  double GetQD() const{ return fQR; }
  double GetQR() const{ return fQR; }
  double qd() const{ return fQR; }
  double qr() const{ return fQR; }
  virtual bool qgood() const; ///< return ql.good() && qr.good()

  double GetHitPosition() const{ return fHitPos; }
  double hitPos() const{ return fHitPos; }
  int GetStripId() const{ return fStripId; }
  int stripId() const{ return fStripId; }
  /// \reval: 1: singly fired; 3: bothly fired, if hitPos good, then 4
  virtual void Print(const char *opt = "") const override; ///< print the hit info
  virtual void ConfigureDraw() override; ///< configure fGHit
  bool optimal() const{ return fIsOptimal; }
  void SetOptimal(){ fIsOptimal = true; }
  void SetTrackId(int id){ fTrkId = id; }
  int GetTrackId() const{ return fTrkId; }
  int trkid() const{ return fTrkId; }

  friend class ETFTOFWall;
  friend class ETFTimer; ///< to invoke non-const version of GetDataChannel

  ClassDefOverride(ETFPlaHit, 1); // ABC for an ETF hit

protected:
  /// to trim the leading edges of L and R end so as to align them in time
  /// choose the pair of edges of UV and DV channels that falls in [trigLB, trigHB] range
  /// and the difference of the two are minimal
  virtual void Filter(double trigLB, double triHB);

  ///< assign those member variables that can only be done after all raw data are assigned
  virtual void Assign() override;
  virtual void AssignFiredStatus(); ///< fired status, hit times and hitPos are assigned here
  virtual void AssignHitQ();

  // firedStatus: 1: singly fired U; 2: singly fired D;
  // 3: bothly fired, if hitPos good, then 4

  static const double VEFF; //! ///< effective light velocity in pla: in mm/ns
  int fLength; //! ///< the distance between the two PMTs
  int fStripId; ///< strip id
  double fHitPos;
  double fTime, fTimeL, fTimeR; ///< L-R, distance to L
  double fQ, fQL, fQR; ///< Q=QL*QR; distance to R
  const ETFHPTDCCh *fUCh[2], *fDCh[2]; //-> ///< [V-H]
  const ETFAmpCh *fQUCh, *fQDCh; //-> ///< QDC info

  /// whether the raw data has been filtered
  bool fFiltered; //! speical for tstop, to get rid of L-R leading edge misalginment
  /// whether this is an optimal hit: not a secondary one fired by 2ndary reactions
  bool fIsOptimal; ///< 0: false; 1: true
  int fTrkId; ///< the track that this plaHit belongs to - specifically for TOFW hits
};

#endif
